#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include "student.hxx"
#include "student-odb.hxx"
#include <gflags/gflags.h>
#include <gtest/gtest.h>

DEFINE_string(host, "127.0.0.1", "这是Mysql服务器地址");
DEFINE_int32(port, 3306, "这是Mysql服务器端口");
DEFINE_string(db, "TestDB", "数据库默认库名称");
DEFINE_string(user, "wzq", "这是Mysql用户名");
DEFINE_string(pswd, "123456", "这是Mysql密码");
DEFINE_string(cset, "utf8", "这是Mysql客户端字符集");
DEFINE_int32(max_pool, 3, "这是Mysql连接池最大连接数量");

// 1. 构造连接池工厂配置对象
std::unique_ptr<odb::mysql::connection_pool_factory> cpf(
    new odb::mysql::connection_pool_factory(FLAGS_max_pool, 0));
// 2. 构造数据库操作对象
// 构造数据库操作对象需要传入：
// Mysql用户名 Mysql密码 数据库默认库名称 Mysql服务器地址 Mysql服务器端口 "" Mysql客户端字符集 连接池工厂配置对象
odb::mysql::database db(
    FLAGS_user,
    FLAGS_pswd,
    FLAGS_db,
    FLAGS_host,
    FLAGS_port,
    "",   // MySQL套接字文件路径 填空串就行
    FLAGS_cset,
    0, std::move(cpf));

TEST(数据插入测试, Test1)
{
    try
    {
        // 3. 获取事务操作对象，开启事务
        odb::mysql::transaction trans(db.begin());
        //构造班级数据
        Classes c1("一年级1班");
        Classes c2("一年级2班");
        //插入
        db.persist(c1);
        db.persist(c2);

        //构造学生信息数据
        Student s1(1, "张三", 18, 1);
        Student s2(2, "李四", 18, 1);
        Student s3(3, "王五", 18, 1);
        Student s4(4, "赵六", 18, 2);
        Student s5(5, "田七", 18, 2);
        Student s6(6, "王八", 18, 2);
        Student s7(7, "Tom", 18, 2);

        //插入
        db.persist(s1);
        db.persist(s2);
        db.persist(s3);
        db.persist(s4);
        db.persist(s5);
        db.persist(s6);
        db.persist(s7);
        //5. 提交事务
        trans.commit();
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }
}

TEST(数据查询测试, Test2)
{
    Student stu;
    try
    {
        odb::mysql::transaction trans(db.begin());

        typedef odb::result<Student> Result; // 查询结果容器
        typedef odb::query<Student> Query;   // 查询限定条件

        // 开始查询
        Result r(db.query<Student>(Query::name == "张三"));
        ASSERT_EQ(r.size(), 1);

        stu = *r.begin();
        trans.commit();
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }

    std::cout<<"学生姓名："<<stu.name()<<std::endl;
    std::cout<<"学生学号："<<stu.sn()<<std::endl;
    if(stu.age()) std::cout<<"学生年龄："<<*stu.age()<<std::endl;
    std::cout<<"学生班级"<<stu.classes_id()<<std::endl;
}

TEST(数据更新, Test3)
{
    try
    {
        odb::mysql::transaction trans(db.begin());
        // 更新要先查找
        Student stu;
        typedef odb::result<Student> Result; // 查询结果容器
        typedef odb::query<Student> Query;   // 查询限定条件
        Result r(db.query<Student>(Query::name == "张三"));
        stu = *r.begin();
        std::cout<<"学生姓名："<<stu.name()<<std::endl;
        std::cout<<"学生学号："<<stu.sn()<<std::endl;
        if(stu.age()) std::cout<<"学生年龄："<<*stu.age()<<std::endl;
        std::cout<<"学生班级"<<stu.classes_id()<<std::endl;
        // 对stu学生数修改
        stu.age(17);
        //更新
        db.update(stu);
        trans.commit();
        if(stu.age()) std::cout<<"更改后学生年龄："<<*stu.age()<<std::endl;
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }
}

TEST(删除数据测试, Test4)
{
     try
    {
        odb::mysql::transaction trans(db.begin());
        typedef odb::query<Student> Query;
        db.erase_query<Student>(Query::name == "Tom");
        trans.commit();
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }
}
int main(int argc, char *argv[])
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    testing::InitGoogleTest(&argc, argv);

    return RUN_ALL_TESTS();
}